<!-------- @HEADER
 !
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !
 !  Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
 !                  Copyright 2012 Sandia Corporation
 !
 ! Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 ! the U.S. Government retains certain rights in this software.
 !
 ! Redistribution and use in source and binary forms, with or without
 ! modification, are permitted provided that the following conditions are
 ! met:
 !
 ! 1. Redistributions of source code must retain the above copyright
 ! notice, this list of conditions and the following disclaimer.
 !
 ! 2. Redistributions in binary form must reproduce the above copyright
 ! notice, this list of conditions and the following disclaimer in the
 ! documentation and/or other materials provided with the distribution.
 !
 ! 3. Neither the name of the Corporation nor the names of the
 ! contributors may be used to endorse or promote products derived from
 ! this software without specific prior written permission.
 !
 ! THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
 ! EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 ! PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
 ! CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 ! EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 ! PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 ! LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 ! NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 !
 ! Questions? Contact Karen Devine	kddevin@sandia.gov
 !                    Erik Boman	egboman@sandia.gov
 !
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 !
 ! @HEADER
-------> 
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <meta name="GENERATOR" content="Mozilla/4.7 [en] (X11; U; SunOS 5.7 sun4u) [Netscape]">
   <meta name="sandia.approved" content="SAND99-1376">
   <meta name="author" content="karen devine, kddevin@sandia.gov">
   <title> Zoltan Developer's Guide:  Adding Data Structures</title>

</head>
<body bgcolor="#FFFFFF">

<div align=right><b><i><a href="dev.html">Zoltan Developer's Guide</a>&nbsp;
|&nbsp; <a href="dev_add_memory.html">Next</a>&nbsp; |&nbsp; <a href="dev_add_lb.html">Previous</a></i></b></div>

<h2>
<a NAME="new_data_structs"></a>Data Structures</h2>
The main data structures for the algorithm should be pointed to by the
<i>LB.Data_Structure</i>
field of the <b><a href="dev_lb_structs.html#Zoltan_Struct">Zoltan_Struct</a></b>.
This requirement allows reuse of data structures from one invocation of
the new load-balancing algorithm to the next. It also prevents the use
of global data structures for the algorithm so that multiple instances
of the algorithm may be used (i.e., the same algorithm can be used for
multiple <b><a href="dev_lb_structs.html#Zoltan_Struct">Zoltan_Struct</a></b> structures).&nbsp;
An example showing the construction of data structures for the 
<a href="../ug_html/ug_alg_rcb.html">Recursive
Coordinate Bisection (RCB)</a> algorithm is included 
in the <a href="#RCB_example">figure</a> below.
<center><table BORDER=2 COLS=1 WIDTH="90%" NOSAVE >
<tr>
<td><a NAME="RCB_example"></a>
<tt>
<br>/* Allocate RCB data structure for this Zoltan structure.
<br>&nbsp;* If the previous data structure still exists, free the Dots
first;
<br>&nbsp;* the other fields can be reused.
<br>&nbsp;*/
<br>if (zz->LB.Data_Structure == NULL) {
<br>&nbsp;&nbsp; rcb = (RCB_STRUCT *) <a href="../ug_html/ug_util_mem.html#Zoltan_Malloc">ZOLTAN_MALLOC</a>(sizeof(RCB_STRUCT));
<br>&nbsp;&nbsp; zz->LB.Data_Structure = (void *) rcb;
<br>&nbsp;&nbsp; rcb->Tree_Ptr = (struct rcb_tree *)&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="../ug_html/ug_util_mem.html#Zoltan_Malloc">ZOLTAN_MALLOC</a>(zz->Num_Proc*sizeof(struct
rcb_tree));
<br>&nbsp;&nbsp; rcb->Box = (struct rcb_box *) <a href="../ug_html/ug_util_mem.html#Zoltan_Malloc">ZOLTAN_MALLOC</a>(sizeof(struct
rcb_box));
<br>}
<br>else {
<br>&nbsp;&nbsp; rcb = (RCB_STRUCT *) zz->LB.Data_Structure;
<br>&nbsp;&nbsp; <a href="../ug_html/ug_util_mem.html#Zoltan_Free">ZOLTAN_FREE</a>(&amp;(rcb->Dots));
<br>}
</tt>
</td>
</tr>

<caption ALIGN=BOTTOM><i>Example demonstrating allocation of data structures
for the RCB algorithm.&nbsp; (Taken from rcb/rcb_util.c.)</i></caption>
</table></center>

<p>The data needed for the algorithm is collected through calls to the
query functions registered by the application. Algorithms should test the
query function pointers for NULL and report errors when needed functions
are not registered. The appropriate query functions can be called to build
the algorithm's data structures up front, or they can be called during
the algorithm's execution to gather data only as it is needed. The <a href="#query_example">figure</a>
below shows how the <i>Dots</i> data structure needed by RCB is built.&nbsp;
The call to <i>zz->Get_Num_Obj</i> invokes an <b><a href="../ug_html/ug_query_lb.html#ZOLTAN_NUM_OBJ_FN">ZOLTAN_NUM_OBJ_FN</a></b>
query function to determine the number of objects on the processor.&nbsp;
Space for the <i>Dots</i> data structure is allocated through calls to
<b><a href="../ug_html/ug_util_mem.html#Zoltan_Malloc">ZOLTAN_MALLOC</a></b>, <a href="dev_lb_types.html#ID alloc"><b>ZOLTAN_MALLOC_GID_ARRAY</b></a>,
and <a href="dev_lb_types.html#ID alloc"><b>ZOLTAN_MALLOC_LID_ARRAY</b></a>.&nbsp; The <i>Dots</i> information is obtained
through a call to the Zoltan service function <b><a href="dev_services_objlist.html">Zoltan_Get_Obj_List</a></b>; this
function calls either an <b><a href="../ug_html/ug_query_lb.html#ZOLTAN_OBJ_LIST_FN">ZOLTAN_OBJ_LIST_FN</a></b>
or an <b><a href="../ug_html/ug_query_lb.html#ZOLTAN_FIRST_OBJ_FN">ZOLTAN_FIRST_OBJ_FN</a></b>/<b><a href="../ug_html/ug_query_lb.html#ZOLTAN_NEXT_OBJ_FN">ZOLTAN_NEXT_OBJ_FN</a></b>
pair to get the object IDs and weights. The data for each
<i>Dot</i> is
set in the function <i>initialize_dot</i>, which includes calls to<i> zz->Get_Geom</i>,
an <b><a href="../ug_html/ug_query_lb.html#ZOLTAN_GEOM_FN">ZOLTAN_GEOM_FN</a></b>
query function.
<br>&nbsp;
<br>&nbsp;
<center><table BORDER=2 COLS=1 WIDTH="90%" NOSAVE >
<tr>
<td><a NAME="query_example"></a>&nbsp;&nbsp;
<tt>
<br>/*
<br>&nbsp;* Allocate space for objects.&nbsp; Allow extra space
<br>&nbsp;* for objects that are imported to the processor.
<br>&nbsp;*/
<p>*num_obj = zz->Get_Num_Obj(zz->Get_Num_Obj_Data, &amp;ierr);
<br>if (ierr) {
<br>&nbsp; <a href="dev_intro_coding.html#ZOLTAN_PRINT">ZOLTAN_PRINT_ERROR</a>(zz->Proc,
yo,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"Error returned from Get_Num_Obj.");
<br>&nbsp; return(ierr);
<br>}
<p>*max_obj = (int)(1.5 * *num_obj) + 1;
<br>*global_ids = <a href="dev_lb_types.html#ID alloc">ZOLTAN_MALLOC_GID_ARRAY</a>(zz, (*max_obj));
<br>*local_ids&nbsp; = <a href="dev_lb_types.html#ID alloc">ZOLTAN_MALLOC_LID_ARRAY</a>(zz, (*max_obj));
<br>*dots = (struct Dot_Struct *)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="../ug_html/ug_util_mem.html#Zoltan_Malloc">ZOLTAN_MALLOC</a>((*max_obj)*sizeof(struct
Dot_Struct));
<p>if (!(*global_ids) || (zz->Num_LID &amp;&amp; !(*local_ids)) ||
!(*dots)) {
<br>&nbsp; <a href="dev_intro_coding.html#ZOLTAN_PRINT">ZOLTAN_PRINT_ERROR</a>(zz->Proc,
yo, "Insufficient memory.");
<br>&nbsp; return(<a href="../ug_html/ug_interface.html#Error Codes">ZOLTAN_MEMERR</a>);
<br>}
<p>if (*num_obj > 0) {
<p>&nbsp; if (wgtflag) {
<p>&nbsp;&nbsp;&nbsp; /*
<br>&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; Allocate space for object weights.
<br>&nbsp;&nbsp;&nbsp;&nbsp; */
<p>&nbsp;&nbsp;&nbsp; objs_wgt = (float *) <a href="../ug_html/ug_util_mem.html#Zoltan_Malloc">ZOLTAN_MALLOC</a>((*num_obj)*sizeof(float));
<br>&nbsp;&nbsp;&nbsp; if (!objs_wgt) {
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="dev_intro_coding.html#ZOLTAN_PRINT">ZOLTAN_PRINT_ERROR</a>(zz->Proc,
yo, "Insufficient memory.");
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return(<a href="../ug_html/ug_interface.html#Error Codes">ZOLTAN_MEMERR</a>);
<br>&nbsp;&nbsp;&nbsp; }
<br>&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; *num_obj; i++) objs_wgt[i]
= 0.;
<br>&nbsp; }
<p>&nbsp; /*
<br>&nbsp;&nbsp; *&nbsp; Get list of objects' IDs and weights.
<br>&nbsp;&nbsp; */
<p>&nbsp; <a href="dev_services_objlist.html">Zoltan_Get_Obj_List</a>(zz, *global_ids, *local_ids, wgtflag, 
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objs_wgt, &amp;ierr);
<br>&nbsp; if (ierr) {
<br>&nbsp;&nbsp;&nbsp; <a href="dev_intro_coding.html#ZOLTAN_PRINT">ZOLTAN_PRINT_ERROR</a>(zz->Proc,
yo,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"Error returned from Zoltan_Get_Obj_List.");
<br>&nbsp;&nbsp;&nbsp; <a href="../ug_html/ug_util_mem.html#Zoltan_Free">ZOLTAN_FREE</a>(&amp;objs_wgt);
<br>&nbsp;&nbsp;&nbsp; return(ierr);
<br>&nbsp; }
<p>&nbsp; ierr = initialize_dot(zz, *global_ids, *local_ids, *dots,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
*num_obj, wgtflag, objs_wgt);
<br>&nbsp; if (ierr == ZOLTAN_FATAL || ierr == ZOLTAN_MEMERR) {
<br>&nbsp;&nbsp;&nbsp; <a href="dev_intro_coding.html#ZOLTAN_PRINT">ZOLTAN_PRINT_ERROR</a>(zz->Proc,
yo,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"Error returned from initialize_dot.");
<br>&nbsp;&nbsp;&nbsp; <a href="../ug_html/ug_util_mem.html#Zoltan_Free">ZOLTAN_FREE</a>(&amp;objs_wgt);
<br>&nbsp;&nbsp;&nbsp; return(ierr);
<br>&nbsp; }
<p>&nbsp; <a href="../ug_html/ug_util_mem.html#Zoltan_Free">ZOLTAN_FREE</a>(&amp;objs_wgt);
<br>}
</tt>
</td>
</tr>

<caption ALIGN=BOTTOM><i>Example demonstrating how data structures are
built for the RCB algorithm.&nbsp; (Taken from rcb/shared.c.)</i></caption>
</table></center>

<p>
The data structures pointed to by <i>zz->LB.Data_Structure</i> will be freed
at some point, and may be copied.
<p>A function that frees these structures and resets <i>zz->LB.Data_Structure</i>
to NULL should be written.  The function should be called when the load-balancing
algorithm exits, either normally or due to an error condition.
The function
<b>Zoltan_RCB_Free_Structure</b> in <i>rcb/rcb_util.c</i> may be used as an example.
<A NAME="Copy"></A>
<p>If your algorithm uses the <a href="../ug_html/ug_alg_rcb.html">KEEP_CUTS</a>
parameter, a function that copies one <i>zz->LB.Data_Structure</i> to another is 
required.  This is particularly important for C++, 
which may create temporary objects
at runtime by invoking a copy operator (which will call your copy function).
It is a convenience for C applications, which may wish to copy one Zoltan_Struct
to another.  
See the function <b>Zoltan_RCB_Copy_Structure</b> in <i>rcb/rcb_util.c</i> 
for an example.  

<hr WIDTH="100%">
<br>[<a href="dev.html">Table of Contents</a>&nbsp; |&nbsp; <a href="dev_add_memory.html">Next:&nbsp;
Memory Management</a>&nbsp; |&nbsp; <a href="dev_add_lb.html">Previous:&nbsp;
Load-Balancing Function Implementation</a>&nbsp; |&nbsp; <a href="https://www.sandia.gov/general/privacy-security/index.html">Privacy and Security</a>]
<br>&nbsp;
</body>
</html>
